// 蜂窝蜜造平台生成代码，如手工更改，请添加到 .beeignore 忽略生成

package com.fowo.api.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fowo.api.common.annotaion.DataObjectType;
import com.fowo.api.common.config.CacheConfig;
import com.fowo.api.common.excel.CustomExcelExport;
import com.fowo.api.common.excel.CustomExcelHandler;
import com.fowo.api.common.excel.ExcelConfig;
import com.fowo.api.common.excel.TemplateModelBuildEventListener;
import com.fowo.api.common.model.ImportRow;
import com.fowo.api.common.model.OptionItem;
import com.fowo.api.common.model.RException;
import com.fowo.api.common.util.ContextHolder;
import com.fowo.api.common.util.DateUtils;
import com.fowo.api.common.util.ResponseUtils;
import com.fowo.api.common.util.SheetUtils;
import com.fowo.api.entity.ShopProfitReport;
import com.fowo.api.flow.entity.WorkFlow;
import com.fowo.api.flow.service.WorkFlowService;
import com.fowo.api.mapper.ShopProfitReportMapper;
import com.fowo.api.mapper.ShopProfitReportOtherFeeMapper;
import com.fowo.api.model.shop.profit.report.ShopProfitReportBatchPushJindieAction;
import com.fowo.api.model.shop.profit.report.ShopProfitReportExcelPo;
import com.fowo.api.model.shop.profit.report.ShopProfitReportImportPo;
import com.fowo.api.model.shop.profit.report.ShopProfitReportItemVo;
import com.fowo.api.model.shop.profit.report.ShopProfitReportPushJindieAction;
import com.fowo.api.model.shop.profit.report.ShopProfitReportSearchParamPo;
import com.fowo.api.model.shop.profit.report.ShopProfitReportSyncLingXingAction;
import com.fowo.api.model.shop.profit.report.ShopProfitReportVo;
import com.fowo.api.model.shop.profit.report.other.fee.ShopProfitReportOtherFeeSearchParamPo;
import com.fowo.api.service.ShopProfitReportOtherFeeService;
import com.fowo.api.service.ShopProfitReportService;
import com.fowo.api.sys.annotation.DataActivity;
import com.fowo.api.sys.component.SysDataActivityAopHelper;
import com.fowo.api.sys.entity.SysFile;
import com.fowo.api.sys.entity.SysImportTemplate;
import com.fowo.api.sys.entity.enums.SysDataActivityAction;
import com.fowo.api.sys.service.FileService;
import com.fowo.api.sys.service.SysImportTemplateService;
import com.fowo.api.user.model.JwtUserInfo;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

/**
 * 利润查询报表-店铺 服务实现类
 * @author 蜂窝蜜造平台 配置人：王冰卿，沈友谅
 */
@Service
@Slf4j
@DataObjectType(ShopProfitReport.class)
@DS("ds24")
public class ShopProfitReportServiceImpl
  extends ServiceImpl<ShopProfitReportMapper, ShopProfitReport>
  implements ShopProfitReportService {

  public static final Map<String, String> SORT_FIELD_MAP = new HashMap<>();
  // 导出时单次查询最大记录数
  protected static final int EXPORT_QUERY_MAX_SIZE = 1000;
  // 支持导出的最大记录数(1048576 为 Excel 支持的最大行数)
  protected static final long EXPORT_MAX_SIZE = 1048575;

  /**
   * 服务自引用，用于调用服务方法时包括 AOP 处理
   */
  @Resource
  protected ShopProfitReportService self;

  @Resource
  protected ShopProfitReportOtherFeeService shopProfitReportOtherFeeService;

  @Resource
  protected FileService fileService;

  @Resource
  protected SysImportTemplateService importTemplateService;

  @Resource
  private CustomExcelExport customExcelExport;

  @Resource
  protected WorkFlowService workFlowService;

  @Autowired(required = false)
  protected ShopProfitReportBatchPushJindieAction shopProfitReportBatchPushJindieAction;

  @Autowired(required = false)
  protected ShopProfitReportSyncLingXingAction shopProfitReportSyncLingXingAction;

  @Autowired(required = false)
  protected ShopProfitReportPushJindieAction shopProfitReportPushJindieAction;

  @Resource
  protected Validator validator;

  /**
   * 创建利润查询报表-店铺
   * @param model 利润查询报表-店铺
   * @return 新数据的主键
   */
  @DataActivity(action = SysDataActivityAction.Add)
  @Transactional(rollbackFor = Exception.class)
  @Override
  public Long create(ShopProfitReportVo model) throws Exception {
    JwtUserInfo currentUser = JwtUserInfo.fromHeader();
    ShopProfitReport entity = new ShopProfitReport();
    BeanUtils.copyProperties(model, entity);
    entity.setCreateTime(new Date());
    entity.setLastUpdateTime(new Date());
    if (currentUser != null) {
      entity.setCreateUser(currentUser.getUserId());
      entity.setLastUpdateUser(currentUser.getUserId());
    }
    if (this.save(entity)) {
      model.setId(entity.getId());
      updateAllChilds(model);
      return entity.getId();
    }
    throw new Exception("利润查询报表-店铺保存失败");
  }

  /**
   * 更新所有子表
   * @param model 利润查询报表-店铺
   */
  protected void updateAllChilds(ShopProfitReportVo model) throws Exception {
    if (model.getOtherFeeStr() != null) {
      shopProfitReportOtherFeeService.saveAllByParentShopProfitReport(
        model.getId(),
        model.getOtherFeeStr()
      );
    }
  }

  /**
   * 更新利润查询报表-店铺
   * @param model 利润查询报表-店铺
   * @return 更新是否成功
   */
  @DataActivity(action = SysDataActivityAction.Modified)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean update(ShopProfitReportVo model) throws Exception {
    JwtUserInfo currentUser = JwtUserInfo.fromHeader();
    ShopProfitReport entity = this.getById(model.getId());
    if (entity == null) {
      throw new Exception("利润查询报表-店铺不存在");
    }
    BeanUtils.copyProperties(
      model,
      entity,
      "id",
      "createTime",
      "createUser",
      "lastUpdateTime",
      "lastUpdateUser"
    );
    entity.setLastUpdateTime(new Date());
    if (currentUser != null) {
      entity.setLastUpdateUser(currentUser.getUserId());
    }
    if (this.updateById(entity)) {
      updateAllChilds(model);
      return true;
    }
    return false;
  }/**
   * 更新利润查询报表-店铺（带空值）
   * @param model 利润查询报表-店铺
   * @return 更新是否成功
   */

  @DataActivity(action = SysDataActivityAction.Modified)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean updateForEdit(ShopProfitReportVo model) throws Exception {
    JwtUserInfo currentUser = JwtUserInfo.fromHeader();
    ShopProfitReport entity = this.getById(model.getId());
    if (entity == null) {
      throw new Exception("利润查询报表-店铺不存在");
    }
    model.setLastUpdateTime(new Date());
    if (currentUser != null) {
      model.setLastUpdateUser(currentUser.getUserId());
    }
    boolean isOk = new LambdaUpdateChainWrapper<>(baseMapper)
      .set(ShopProfitReport::getLastUpdateTime, model.getLastUpdateTime())
      .set(ShopProfitReport::getLastUpdateUser, model.getLastUpdateUser())
      .set(ShopProfitReport::getPostedDateLocale, model.getPostedDateLocale())
      .set(
        ShopProfitReport::getTotalSalesQuantity,
        model.getTotalSalesQuantity()
      )
      .set(ShopProfitReport::getFbaSalesQuantity, model.getFbaSalesQuantity())
      .set(ShopProfitReport::getFbmSalesQuantity, model.getFbmSalesQuantity())
      .set(
        ShopProfitReport::getTotalReshipQuantity,
        model.getTotalReshipQuantity()
      )
      .set(
        ShopProfitReport::getReshipFbmProductSalesQuantity,
        model.getReshipFbmProductSalesQuantity()
      )
      .set(
        ShopProfitReport::getReshipFbmProductSaleRefundsQuantity,
        model.getReshipFbmProductSaleRefundsQuantity()
      )
      .set(
        ShopProfitReport::getReshipFbaProductSalesQuantity,
        model.getReshipFbaProductSalesQuantity()
      )
      .set(
        ShopProfitReport::getReshipFbaProductSaleRefundsQuantity,
        model.getReshipFbaProductSaleRefundsQuantity()
      )
      .set(ShopProfitReport::getTotalAdsSales, model.getTotalAdsSales())
      .set(ShopProfitReport::getAdsSdSales, model.getAdsSdSales())
      .set(ShopProfitReport::getStoreName, model.getStoreName())
      .set(ShopProfitReport::getAdsSpSales, model.getAdsSpSales())
      .set(ShopProfitReport::getSharedAdsSbSales, model.getSharedAdsSbSales())
      .set(ShopProfitReport::getSharedAdsSbvSales, model.getSharedAdsSbvSales())
      .set(
        ShopProfitReport::getTotalAdsSalesQuantity,
        model.getTotalAdsSalesQuantity()
      )
      .set(
        ShopProfitReport::getAdsSdSalesQuantity,
        model.getAdsSdSalesQuantity()
      )
      .set(
        ShopProfitReport::getAdsSpSalesQuantity,
        model.getAdsSpSalesQuantity()
      )
      .set(
        ShopProfitReport::getSharedAdsSbSalesQuantity,
        model.getSharedAdsSbSalesQuantity()
      )
      .set(
        ShopProfitReport::getSharedAdsSbvSalesQuantity,
        model.getSharedAdsSbvSalesQuantity()
      )
      .set(ShopProfitReport::getTotalSalesAmount, model.getTotalSalesAmount())
      .set(ShopProfitReport::getFbaSaleAmount, model.getFbaSaleAmount())
      .set(ShopProfitReport::getFbmSaleAmount, model.getFbmSaleAmount())
      .set(
        ShopProfitReport::getMcFbaFulfillmentFeesQuantity,
        model.getMcFbaFulfillmentFeesQuantity()
      )
      .set(ShopProfitReport::getShippingCredits, model.getShippingCredits())
      .set(
        ShopProfitReport::getPromotionalRebates,
        model.getPromotionalRebates()
      )
      .set(
        ShopProfitReport::getFbaInventoryCredit,
        model.getFbaInventoryCredit()
      )
      .set(ShopProfitReport::getCashOnDelivery, model.getCashOnDelivery())
      .set(ShopProfitReport::getOtherInAmount, model.getOtherInAmount())
      .set(
        ShopProfitReport::getFbaLiquidationProceeds,
        model.getFbaLiquidationProceeds()
      )
      .set(
        ShopProfitReport::getFbaLiquidationProceedsAdjustments,
        model.getFbaLiquidationProceedsAdjustments()
      )
      .set(
        ShopProfitReport::getAmazonShippingReimbursement,
        model.getAmazonShippingReimbursement()
      )
      .set(
        ShopProfitReport::getSafeTReimbursement,
        model.getSafeTReimbursement()
      )
      .set(ShopProfitReport::getNetcoTransaction, model.getNetcoTransaction())
      .set(ShopProfitReport::getReimbursements, model.getReimbursements())
      .set(ShopProfitReport::getClawbacks, model.getClawbacks())
      .set(
        ShopProfitReport::getSharedComminglingVatIncome,
        model.getSharedComminglingVatIncome()
      )
      .set(ShopProfitReport::getGiftWrapCredits, model.getGiftWrapCredits())
      .set(ShopProfitReport::getGuaranteeClaims, model.getGuaranteeClaims())
      .set(
        ShopProfitReport::getCostOfPoIntegersGranted,
        model.getCostOfPoIntegersGranted()
      )
      .set(ShopProfitReport::getTotalSalesRefunds, model.getTotalSalesRefunds())
      .set(ShopProfitReport::getFbaSalesRefunds, model.getFbaSalesRefunds())
      .set(ShopProfitReport::getFbmSalesRefunds, model.getFbmSalesRefunds())
      .set(
        ShopProfitReport::getShippingCreditRefunds,
        model.getShippingCreditRefunds()
      )
      .set(
        ShopProfitReport::getGiftWrapCreditRefunds,
        model.getGiftWrapCreditRefunds()
      )
      .set(ShopProfitReport::getChargebacks, model.getChargebacks())
      .set(
        ShopProfitReport::getCostOfPoIntegersReturned,
        model.getCostOfPoIntegersReturned()
      )
      .set(
        ShopProfitReport::getPromotionalRebateRefunds,
        model.getPromotionalRebateRefunds()
      )
      .set(ShopProfitReport::getTotalFeeRefunds, model.getTotalFeeRefunds())
      .set(ShopProfitReport::getSellingFeeRefunds, model.getSellingFeeRefunds())
      .set(
        ShopProfitReport::getFbaTransactionFeeRefunds,
        model.getFbaTransactionFeeRefunds()
      )
      .set(
        ShopProfitReport::getRefundAdministrationFees,
        model.getRefundAdministrationFees()
      )
      .set(
        ShopProfitReport::getOtherTransactionFeeRefunds,
        model.getOtherTransactionFeeRefunds()
      )
      .set(
        ShopProfitReport::getRefundForAdvertiser,
        model.getRefundForAdvertiser()
      )
      .set(ShopProfitReport::getPointsAdjusted, model.getPointsAdjusted())
      .set(
        ShopProfitReport::getShippingLabelRefunds,
        model.getShippingLabelRefunds()
      )
      .set(ShopProfitReport::getRefundsQuantity, model.getRefundsQuantity())
      .set(ShopProfitReport::getRefundsRate, model.getRefundsRate())
      .set(
        ShopProfitReport::getFbaReturnsQuantity,
        model.getFbaReturnsQuantity()
      )
      .set(
        ShopProfitReport::getFbaReturnsSaleableQuantity,
        model.getFbaReturnsSaleableQuantity()
      )
      .set(
        ShopProfitReport::getFbaReturnsUnsaleableQuantity,
        model.getFbaReturnsUnsaleableQuantity()
      )
      .set(
        ShopProfitReport::getFbaReturnsQuantityRate,
        model.getFbaReturnsQuantityRate()
      )
      .set(ShopProfitReport::getPlatformFee, model.getPlatformFee())
      .set(ShopProfitReport::getFbaDeliveryFee, model.getFbaDeliveryFee())
      .set(ShopProfitReport::getMcFbaDeliveryFee, model.getMcFbaDeliveryFee())
      .set(
        ShopProfitReport::getTotalFbaDeliveryFee,
        model.getTotalFbaDeliveryFee()
      )
      .set(
        ShopProfitReport::getOtherTransactionFees,
        model.getOtherTransactionFees()
      )
      .set(ShopProfitReport::getTotalAdsCost, model.getTotalAdsCost())
      .set(ShopProfitReport::getAdsSpCost, model.getAdsSpCost())
      .set(ShopProfitReport::getAdsSbCost, model.getAdsSbCost())
      .set(ShopProfitReport::getAdsSbvCost, model.getAdsSbvCost())
      .set(ShopProfitReport::getAdsSdCost, model.getAdsSdCost())
      .set(
        ShopProfitReport::getSharedCostOfAdvertising,
        model.getSharedCostOfAdvertising()
      )
      .set(ShopProfitReport::getPromotionFee, model.getPromotionFee())
      .set(
        ShopProfitReport::getSharedSubscriptionFee,
        model.getSharedSubscriptionFee()
      )
      .set(ShopProfitReport::getSharedLdFee, model.getSharedLdFee())
      .set(ShopProfitReport::getSharedCouponFee, model.getSharedCouponFee())
      .set(
        ShopProfitReport::getSharedEarlyReviewerProgramFee,
        model.getSharedEarlyReviewerProgramFee()
      )
      .set(ShopProfitReport::getSharedVineFee, model.getSharedVineFee())
      .set(ShopProfitReport::getTotalStorageFee, model.getTotalStorageFee())
      .set(ShopProfitReport::getFbaStorageFee, model.getFbaStorageFee())
      .set(
        ShopProfitReport::getSharedFbaStorageFee,
        model.getSharedFbaStorageFee()
      )
      .set(
        ShopProfitReport::getLongTermStorageFee,
        model.getLongTermStorageFee()
      )
      .set(
        ShopProfitReport::getSharedLongTermStorageFee,
        model.getSharedLongTermStorageFee()
      )
      .set(
        ShopProfitReport::getSharedStorageRenewalBilling,
        model.getSharedStorageRenewalBilling()
      )
      .set(
        ShopProfitReport::getSharedFbaDisposalFee,
        model.getSharedFbaDisposalFee()
      )
      .set(
        ShopProfitReport::getSharedFbaRemovalFee,
        model.getSharedFbaRemovalFee()
      )
      .set(
        ShopProfitReport::getSharedFbaInboundTransportationProgramFee,
        model.getSharedFbaInboundTransportationProgramFee()
      )
      .set(ShopProfitReport::getSharedLabelingFee, model.getSharedLabelingFee())
      .set(
        ShopProfitReport::getSharedPolybaggingFee,
        model.getSharedPolybaggingFee()
      )
      .set(
        ShopProfitReport::getSharedBubblewrapFee,
        model.getSharedBubblewrapFee()
      )
      .set(ShopProfitReport::getSharedTapingFee, model.getSharedTapingFee())
      .set(
        ShopProfitReport::getSharedFbaCustomerReturnFee,
        model.getSharedFbaCustomerReturnFee()
      )
      .set(
        ShopProfitReport::getSharedFbaInboundDefectFee,
        model.getSharedFbaInboundDefectFee()
      )
      .set(
        ShopProfitReport::getSharedFbaOverageFee,
        model.getSharedFbaOverageFee()
      )
      .set(
        ShopProfitReport::getSharedAmazonPartneredCarrierShipmentFee,
        model.getSharedAmazonPartneredCarrierShipmentFee()
      )
      .set(
        ShopProfitReport::getSharedFbaInboundConvenienceFee,
        model.getSharedFbaInboundConvenienceFee()
      )
      .set(
        ShopProfitReport::getSharedItemFeeAdjustment,
        model.getSharedItemFeeAdjustment()
      )
      .set(
        ShopProfitReport::getSharedOtherFbaInventoryFees,
        model.getSharedOtherFbaInventoryFees()
      )
      .set(
        ShopProfitReport::getFbaStorageFeeAccrual,
        model.getFbaStorageFeeAccrual()
      )
      .set(
        ShopProfitReport::getFbaStorageFeeAccrualDifference,
        model.getFbaStorageFeeAccrualDifference()
      )
      .set(
        ShopProfitReport::getLongTermStorageFeeAccrual,
        model.getLongTermStorageFeeAccrual()
      )
      .set(
        ShopProfitReport::getLongTermStorageFeeAccrualDifference,
        model.getLongTermStorageFeeAccrualDifference()
      )
      .set(
        ShopProfitReport::getSharedFbaIntegerernationalInboundFee,
        model.getSharedFbaIntegerernationalInboundFee()
      )
      .set(ShopProfitReport::getAdjustments, model.getAdjustments())
      .set(
        ShopProfitReport::getTotalPlatformOtherFee,
        model.getTotalPlatformOtherFee()
      )
      .set(
        ShopProfitReport::getShippingLabelPurchases,
        model.getShippingLabelPurchases()
      )
      .set(
        ShopProfitReport::getSharedCarrierShippingLabelAdjustments,
        model.getSharedCarrierShippingLabelAdjustments()
      )
      .set(
        ShopProfitReport::getSharedLiquidationsFees,
        model.getSharedLiquidationsFees()
      )
      .set(
        ShopProfitReport::getSharedManualProcessingFee,
        model.getSharedManualProcessingFee()
      )
      .set(
        ShopProfitReport::getSharedOtherServiceFees,
        model.getSharedOtherServiceFees()
      )
      .set(ShopProfitReport::getTotalSalesTax, model.getTotalSalesTax())
      .set(ShopProfitReport::getTaxCollected, model.getTaxCollected())
      .set(ShopProfitReport::getTcsIgstCollected, model.getTcsIgstCollected())
      .set(ShopProfitReport::getTcsSgstCollected, model.getTcsSgstCollected())
      .set(ShopProfitReport::getTcsCgstCollected, model.getTcsCgstCollected())
      .set(
        ShopProfitReport::getSharedComminglingVatExpenses,
        model.getSharedComminglingVatExpenses()
      )
      .set(ShopProfitReport::getSalesTaxRefund, model.getSalesTaxRefund())
      .set(ShopProfitReport::getTaxRefunded, model.getTaxRefunded())
      .set(ShopProfitReport::getTcsIgstRefunded, model.getTcsIgstRefunded())
      .set(ShopProfitReport::getTcsSgstRefunded, model.getTcsSgstRefunded())
      .set(ShopProfitReport::getTcsCgstRefunded, model.getTcsCgstRefunded())
      .set(ShopProfitReport::getSalesTaxWithheld, model.getSalesTaxWithheld())
      .set(ShopProfitReport::getRefundTaxWithheld, model.getRefundTaxWithheld())
      .set(ShopProfitReport::getTdsSection194ONet, model.getTdsSection194ONet())
      .set(ShopProfitReport::getCgPriceTotal, model.getCgPriceTotal())
      .set(ShopProfitReport::getHasCgPriceDetail, model.getHasCgPriceDetail())
      .set(ShopProfitReport::getCgUnitPrice, model.getCgUnitPrice())
      .set(ShopProfitReport::getProportionOfCg, model.getProportionOfCg())
      .set(
        ShopProfitReport::getCgTransportCostsTotal,
        model.getCgTransportCostsTotal()
      )
      .set(
        ShopProfitReport::getHasCgTransportCostsDetail,
        model.getHasCgTransportCostsDetail()
      )
      .set(
        ShopProfitReport::getCgTransportUnitCosts,
        model.getCgTransportUnitCosts()
      )
      .set(
        ShopProfitReport::getProportionOfCgTransport,
        model.getProportionOfCgTransport()
      )
      .set(ShopProfitReport::getTotalCost, model.getTotalCost())
      .set(
        ShopProfitReport::getProportionOfTotalCost,
        model.getProportionOfTotalCost()
      )
      .set(ShopProfitReport::getCgOtherCostsTotal, model.getCgOtherCostsTotal())
      .set(ShopProfitReport::getCgOtherUnitCosts, model.getCgOtherUnitCosts())
      .set(
        ShopProfitReport::getHasCgOtherCostsDetail,
        model.getHasCgOtherCostsDetail()
      )
      .set(
        ShopProfitReport::getProportionOfCgOtherCosts,
        model.getProportionOfCgOtherCosts()
      )
      .set(ShopProfitReport::getGrossProfit, model.getGrossProfit())
      .set(ShopProfitReport::getGrossRate, model.getGrossRate())
      .set(ShopProfitReport::getSid, model.getSid())
      .set(ShopProfitReport::getCurrencyCode, model.getCurrencyCode())
      .set(ShopProfitReport::getCurrencyIcon, model.getCurrencyIcon())
      .set(ShopProfitReport::getIsPush, model.getIsPush())
      .set(ShopProfitReport::getPushResult, model.getPushResult())
      .eq(ShopProfitReport::getId, model.getId())
      .update();
    if (isOk) {
      updateAllChilds(model);
    }
    return isOk;
  }

  /**
   * 是否走导出中心
   */
  @Override
  public boolean getBackgroundExportFlag(ShopProfitReportSearchParamPo search) {
    return false;
  }

  /**
   * 批量删除指定主键列表关联的所有子表数据(此方法不包括事务，必须由其它已包括事务的方法调用)
   */
  protected void batchDeleteChilds(List<Long> ids) throws Exception {
    // 处理子表字段 其他费信息(otherFeeStr) 对应的对象
    ShopProfitReportOtherFeeSearchParamPo otherFeeStrSearchParam =
      new ShopProfitReportOtherFeeSearchParamPo();
    otherFeeStrSearchParam.setDisableDataPremissions(true);
    otherFeeStrSearchParam.setParentShopProfitReportInList(ids);
    ShopProfitReportOtherFeeMapper localShopProfitReportOtherFeeMapper =
      ContextHolder
        .getApplicationContext()
        .getBean(ShopProfitReportOtherFeeMapper.class);
    otherFeeStrSearchParam.applySqlSegments();
    List<Long> otherFeeStrIdList =
      localShopProfitReportOtherFeeMapper.searchIds(otherFeeStrSearchParam);
    if (!otherFeeStrIdList.isEmpty()) {
      ShopProfitReportOtherFeeService localShopProfitReportOtherFeeService =
        ContextHolder
          .getApplicationContext()
          .getBean(ShopProfitReportOtherFeeService.class);
      localShopProfitReportOtherFeeService.batchDelete(otherFeeStrIdList);
    }
  }

  /**
   * 删除利润查询报表-店铺
   * @param id 利润查询报表-店铺的主键
   * @return 删除是否成功
   */
  @DataActivity(action = SysDataActivityAction.Del)
  @Override
  public boolean delete(Long id) throws Exception {
    batchDeleteChilds(Collections.singletonList(id));
    return this.removeById(id);
  }

  /**
   * 批量删除利润查询报表-店铺
   * @param ids 利润查询报表-店铺的主键列表
   * @return 删除是否成功
   */
  @DataActivity(action = SysDataActivityAction.Del)
  @Override
  public boolean batchDelete(List<Long> ids) throws Exception {
    batchDeleteChilds(ids);

    int count = 0;
    for (int i = 0; i < ids.size(); i += 2000) {
      count +=
        baseMapper.deleteBatchIds(
          ids.stream().skip(i).limit(2000).collect(Collectors.toList())
        );
    }
    return count > 0;
  }

  /**
   * 导入单行处理
   * @param row 要导入的行
   * @param rowNumber 所在行号
   * @param vo 输出VO,可空
   * @param variables 变量池，用于在一次导入过程中保存临时信息
   * @param allowOverrides 允许覆盖
   * @return 导入行对象
   */
  protected ImportRow<ShopProfitReportImportPo> excelToImportRow(
    ShopProfitReportImportPo row,
    Integer rowNumber,
    ShopProfitReportVo vo,
    Map<String, Object> variables,
    boolean allowOverrides
  ) {
    ImportRow<ShopProfitReportImportPo> ir =
      new ImportRow<ShopProfitReportImportPo>();
    ir.setRowNumber(rowNumber);
    ir.setRow(row);
    if (SheetUtils.isAllFieldsEmpty(row)) {
      ir.setEmptyRow(true);
      ir.addError("", "空行");
      return ir;
    }
    final Set<ConstraintViolation<ShopProfitReportImportPo>> validate =
      validator.validate(row);
    boolean isOutputVo = vo != null;
    if (!isOutputVo) {
      vo = new ShopProfitReportVo();
    }
    BeanUtils.copyProperties(row, vo);
    // 收集基本校验错误
    ir.initErrors(validate, ShopProfitReportImportPo.class);

    // 一般数据处理
    vo.setPostedDateLocale(SheetUtils.tryToDate(row.getPostedDateLocale()));
    SheetUtils.datePreviewFormat(
      row.getPostedDateLocale(),
      row::setPostedDateLocale
    );
    vo.setTotalSalesQuantity(
      SheetUtils.tryToInteger(row.getTotalSalesQuantity())
    );
    vo.setFbaSalesQuantity(SheetUtils.tryToInteger(row.getFbaSalesQuantity()));
    vo.setFbmSalesQuantity(SheetUtils.tryToInteger(row.getFbmSalesQuantity()));
    vo.setTotalReshipQuantity(
      SheetUtils.tryToInteger(row.getTotalReshipQuantity())
    );
    vo.setReshipFbmProductSalesQuantity(
      SheetUtils.tryToInteger(row.getReshipFbmProductSalesQuantity())
    );
    vo.setReshipFbmProductSaleRefundsQuantity(
      SheetUtils.tryToInteger(row.getReshipFbmProductSaleRefundsQuantity())
    );
    vo.setReshipFbaProductSalesQuantity(
      SheetUtils.tryToInteger(row.getReshipFbaProductSalesQuantity())
    );
    vo.setReshipFbaProductSaleRefundsQuantity(
      SheetUtils.tryToInteger(row.getReshipFbaProductSaleRefundsQuantity())
    );
    vo.setTotalAdsSales(SheetUtils.tryToDecimal(row.getTotalAdsSales()));
    vo.setAdsSdSales(SheetUtils.tryToDecimal(row.getAdsSdSales()));
    vo.setAdsSpSales(SheetUtils.tryToDecimal(row.getAdsSpSales()));
    vo.setSharedAdsSbSales(SheetUtils.tryToDecimal(row.getSharedAdsSbSales()));
    vo.setSharedAdsSbvSales(
      SheetUtils.tryToDecimal(row.getSharedAdsSbvSales())
    );
    vo.setTotalAdsSalesQuantity(
      SheetUtils.tryToInteger(row.getTotalAdsSalesQuantity())
    );
    vo.setAdsSdSalesQuantity(
      SheetUtils.tryToInteger(row.getAdsSdSalesQuantity())
    );
    vo.setAdsSpSalesQuantity(
      SheetUtils.tryToInteger(row.getAdsSpSalesQuantity())
    );
    vo.setSharedAdsSbSalesQuantity(
      SheetUtils.tryToInteger(row.getSharedAdsSbSalesQuantity())
    );
    vo.setSharedAdsSbvSalesQuantity(
      SheetUtils.tryToInteger(row.getSharedAdsSbvSalesQuantity())
    );
    vo.setTotalSalesAmount(SheetUtils.tryToDecimal(row.getTotalSalesAmount()));
    vo.setFbaSaleAmount(SheetUtils.tryToDecimal(row.getFbaSaleAmount()));
    vo.setFbmSaleAmount(SheetUtils.tryToDecimal(row.getFbmSaleAmount()));
    vo.setMcFbaFulfillmentFeesQuantity(
      SheetUtils.tryToInteger(row.getMcFbaFulfillmentFeesQuantity())
    );
    vo.setShippingCredits(SheetUtils.tryToDecimal(row.getShippingCredits()));
    vo.setPromotionalRebates(
      SheetUtils.tryToDecimal(row.getPromotionalRebates())
    );
    vo.setFbaInventoryCredit(
      SheetUtils.tryToDecimal(row.getFbaInventoryCredit())
    );
    vo.setCashOnDelivery(SheetUtils.tryToDecimal(row.getCashOnDelivery()));
    vo.setOtherInAmount(SheetUtils.tryToDecimal(row.getOtherInAmount()));
    vo.setFbaLiquidationProceeds(
      SheetUtils.tryToDecimal(row.getFbaLiquidationProceeds())
    );
    vo.setFbaLiquidationProceedsAdjustments(
      SheetUtils.tryToDecimal(row.getFbaLiquidationProceedsAdjustments())
    );
    vo.setAmazonShippingReimbursement(
      SheetUtils.tryToDecimal(row.getAmazonShippingReimbursement())
    );
    vo.setSafeTReimbursement(
      SheetUtils.tryToDecimal(row.getSafeTReimbursement())
    );
    vo.setNetcoTransaction(SheetUtils.tryToDecimal(row.getNetcoTransaction()));
    vo.setReimbursements(SheetUtils.tryToDecimal(row.getReimbursements()));
    vo.setClawbacks(SheetUtils.tryToDecimal(row.getClawbacks()));
    vo.setSharedComminglingVatIncome(
      SheetUtils.tryToDecimal(row.getSharedComminglingVatIncome())
    );
    vo.setGiftWrapCredits(SheetUtils.tryToDecimal(row.getGiftWrapCredits()));
    vo.setGuaranteeClaims(SheetUtils.tryToDecimal(row.getGuaranteeClaims()));
    vo.setCostOfPoIntegersGranted(
      SheetUtils.tryToDecimal(row.getCostOfPoIntegersGranted())
    );
    vo.setTotalSalesRefunds(
      SheetUtils.tryToDecimal(row.getTotalSalesRefunds())
    );
    vo.setFbaSalesRefunds(SheetUtils.tryToDecimal(row.getFbaSalesRefunds()));
    vo.setFbmSalesRefunds(SheetUtils.tryToDecimal(row.getFbmSalesRefunds()));
    vo.setShippingCreditRefunds(
      SheetUtils.tryToDecimal(row.getShippingCreditRefunds())
    );
    vo.setGiftWrapCreditRefunds(
      SheetUtils.tryToDecimal(row.getGiftWrapCreditRefunds())
    );
    vo.setChargebacks(SheetUtils.tryToDecimal(row.getChargebacks()));
    vo.setCostOfPoIntegersReturned(
      SheetUtils.tryToDecimal(row.getCostOfPoIntegersReturned())
    );
    vo.setPromotionalRebateRefunds(
      SheetUtils.tryToDecimal(row.getPromotionalRebateRefunds())
    );
    vo.setTotalFeeRefunds(SheetUtils.tryToDecimal(row.getTotalFeeRefunds()));
    vo.setSellingFeeRefunds(
      SheetUtils.tryToDecimal(row.getSellingFeeRefunds())
    );
    vo.setFbaTransactionFeeRefunds(
      SheetUtils.tryToDecimal(row.getFbaTransactionFeeRefunds())
    );
    vo.setRefundAdministrationFees(
      SheetUtils.tryToDecimal(row.getRefundAdministrationFees())
    );
    vo.setOtherTransactionFeeRefunds(
      SheetUtils.tryToDecimal(row.getOtherTransactionFeeRefunds())
    );
    vo.setRefundForAdvertiser(
      SheetUtils.tryToDecimal(row.getRefundForAdvertiser())
    );
    vo.setPointsAdjusted(SheetUtils.tryToDecimal(row.getPointsAdjusted()));
    vo.setShippingLabelRefunds(
      SheetUtils.tryToDecimal(row.getShippingLabelRefunds())
    );
    vo.setRefundsQuantity(SheetUtils.tryToInteger(row.getRefundsQuantity()));
    vo.setRefundsRate(SheetUtils.tryToDecimal(row.getRefundsRate()));
    vo.setFbaReturnsQuantity(
      SheetUtils.tryToInteger(row.getFbaReturnsQuantity())
    );
    vo.setFbaReturnsSaleableQuantity(
      SheetUtils.tryToInteger(row.getFbaReturnsSaleableQuantity())
    );
    vo.setFbaReturnsUnsaleableQuantity(
      SheetUtils.tryToInteger(row.getFbaReturnsUnsaleableQuantity())
    );
    vo.setFbaReturnsQuantityRate(
      SheetUtils.tryToDecimal(row.getFbaReturnsQuantityRate())
    );
    vo.setPlatformFee(SheetUtils.tryToDecimal(row.getPlatformFee()));
    vo.setFbaDeliveryFee(SheetUtils.tryToDecimal(row.getFbaDeliveryFee()));
    vo.setMcFbaDeliveryFee(SheetUtils.tryToDecimal(row.getMcFbaDeliveryFee()));
    vo.setTotalFbaDeliveryFee(
      SheetUtils.tryToDecimal(row.getTotalFbaDeliveryFee())
    );
    vo.setOtherTransactionFees(
      SheetUtils.tryToDecimal(row.getOtherTransactionFees())
    );
    vo.setTotalAdsCost(SheetUtils.tryToDecimal(row.getTotalAdsCost()));
    vo.setAdsSpCost(SheetUtils.tryToDecimal(row.getAdsSpCost()));
    vo.setAdsSbCost(SheetUtils.tryToDecimal(row.getAdsSbCost()));
    vo.setAdsSbvCost(SheetUtils.tryToDecimal(row.getAdsSbvCost()));
    vo.setAdsSdCost(SheetUtils.tryToDecimal(row.getAdsSdCost()));
    vo.setSharedCostOfAdvertising(
      SheetUtils.tryToDecimal(row.getSharedCostOfAdvertising())
    );
    vo.setPromotionFee(SheetUtils.tryToDecimal(row.getPromotionFee()));
    vo.setSharedSubscriptionFee(
      SheetUtils.tryToDecimal(row.getSharedSubscriptionFee())
    );
    vo.setSharedLdFee(SheetUtils.tryToDecimal(row.getSharedLdFee()));
    vo.setSharedCouponFee(SheetUtils.tryToDecimal(row.getSharedCouponFee()));
    vo.setSharedEarlyReviewerProgramFee(
      SheetUtils.tryToDecimal(row.getSharedEarlyReviewerProgramFee())
    );
    vo.setSharedVineFee(SheetUtils.tryToDecimal(row.getSharedVineFee()));
    vo.setTotalStorageFee(SheetUtils.tryToDecimal(row.getTotalStorageFee()));
    vo.setFbaStorageFee(SheetUtils.tryToDecimal(row.getFbaStorageFee()));
    vo.setSharedFbaStorageFee(
      SheetUtils.tryToDecimal(row.getSharedFbaStorageFee())
    );
    vo.setLongTermStorageFee(
      SheetUtils.tryToDecimal(row.getLongTermStorageFee())
    );
    vo.setSharedLongTermStorageFee(
      SheetUtils.tryToDecimal(row.getSharedLongTermStorageFee())
    );
    vo.setSharedStorageRenewalBilling(
      SheetUtils.tryToDecimal(row.getSharedStorageRenewalBilling())
    );
    vo.setSharedFbaDisposalFee(
      SheetUtils.tryToDecimal(row.getSharedFbaDisposalFee())
    );
    vo.setSharedFbaRemovalFee(
      SheetUtils.tryToDecimal(row.getSharedFbaRemovalFee())
    );
    vo.setSharedFbaInboundTransportationProgramFee(
      SheetUtils.tryToDecimal(row.getSharedFbaInboundTransportationProgramFee())
    );
    vo.setSharedLabelingFee(
      SheetUtils.tryToDecimal(row.getSharedLabelingFee())
    );
    vo.setSharedPolybaggingFee(
      SheetUtils.tryToDecimal(row.getSharedPolybaggingFee())
    );
    vo.setSharedBubblewrapFee(
      SheetUtils.tryToDecimal(row.getSharedBubblewrapFee())
    );
    vo.setSharedTapingFee(SheetUtils.tryToDecimal(row.getSharedTapingFee()));
    vo.setSharedFbaCustomerReturnFee(
      SheetUtils.tryToDecimal(row.getSharedFbaCustomerReturnFee())
    );
    vo.setSharedFbaInboundDefectFee(
      SheetUtils.tryToDecimal(row.getSharedFbaInboundDefectFee())
    );
    vo.setSharedFbaOverageFee(
      SheetUtils.tryToDecimal(row.getSharedFbaOverageFee())
    );
    vo.setSharedAmazonPartneredCarrierShipmentFee(
      SheetUtils.tryToDecimal(row.getSharedAmazonPartneredCarrierShipmentFee())
    );
    vo.setSharedFbaInboundConvenienceFee(
      SheetUtils.tryToDecimal(row.getSharedFbaInboundConvenienceFee())
    );
    vo.setSharedItemFeeAdjustment(
      SheetUtils.tryToDecimal(row.getSharedItemFeeAdjustment())
    );
    vo.setSharedOtherFbaInventoryFees(
      SheetUtils.tryToDecimal(row.getSharedOtherFbaInventoryFees())
    );
    vo.setFbaStorageFeeAccrual(
      SheetUtils.tryToDecimal(row.getFbaStorageFeeAccrual())
    );
    vo.setFbaStorageFeeAccrualDifference(
      SheetUtils.tryToDecimal(row.getFbaStorageFeeAccrualDifference())
    );
    vo.setLongTermStorageFeeAccrual(
      SheetUtils.tryToDecimal(row.getLongTermStorageFeeAccrual())
    );
    vo.setLongTermStorageFeeAccrualDifference(
      SheetUtils.tryToDecimal(row.getLongTermStorageFeeAccrualDifference())
    );
    vo.setSharedFbaIntegerernationalInboundFee(
      SheetUtils.tryToDecimal(row.getSharedFbaIntegerernationalInboundFee())
    );
    vo.setAdjustments(SheetUtils.tryToDecimal(row.getAdjustments()));
    vo.setTotalPlatformOtherFee(
      SheetUtils.tryToDecimal(row.getTotalPlatformOtherFee())
    );
    vo.setShippingLabelPurchases(
      SheetUtils.tryToDecimal(row.getShippingLabelPurchases())
    );
    vo.setSharedCarrierShippingLabelAdjustments(
      SheetUtils.tryToDecimal(row.getSharedCarrierShippingLabelAdjustments())
    );
    vo.setSharedLiquidationsFees(
      SheetUtils.tryToDecimal(row.getSharedLiquidationsFees())
    );
    vo.setSharedManualProcessingFee(
      SheetUtils.tryToDecimal(row.getSharedManualProcessingFee())
    );
    vo.setSharedOtherServiceFees(
      SheetUtils.tryToDecimal(row.getSharedOtherServiceFees())
    );
    vo.setTotalSalesTax(SheetUtils.tryToDecimal(row.getTotalSalesTax()));
    vo.setTaxCollected(SheetUtils.tryToDecimal(row.getTaxCollected()));
    vo.setTcsIgstCollected(SheetUtils.tryToDecimal(row.getTcsIgstCollected()));
    vo.setTcsSgstCollected(SheetUtils.tryToDecimal(row.getTcsSgstCollected()));
    vo.setTcsCgstCollected(SheetUtils.tryToDecimal(row.getTcsCgstCollected()));
    vo.setSharedComminglingVatExpenses(
      SheetUtils.tryToDecimal(row.getSharedComminglingVatExpenses())
    );
    vo.setSalesTaxRefund(SheetUtils.tryToDecimal(row.getSalesTaxRefund()));
    vo.setTaxRefunded(SheetUtils.tryToDecimal(row.getTaxRefunded()));
    vo.setTcsIgstRefunded(SheetUtils.tryToDecimal(row.getTcsIgstRefunded()));
    vo.setTcsSgstRefunded(SheetUtils.tryToDecimal(row.getTcsSgstRefunded()));
    vo.setTcsCgstRefunded(SheetUtils.tryToDecimal(row.getTcsCgstRefunded()));
    vo.setSalesTaxWithheld(SheetUtils.tryToDecimal(row.getSalesTaxWithheld()));
    vo.setRefundTaxWithheld(
      SheetUtils.tryToDecimal(row.getRefundTaxWithheld())
    );
    vo.setTdsSection194ONet(
      SheetUtils.tryToDecimal(row.getTdsSection194ONet())
    );
    vo.setCgPriceTotal(SheetUtils.tryToDecimal(row.getCgPriceTotal()));
    vo.setHasCgPriceDetail(SheetUtils.tryToInteger(row.getHasCgPriceDetail()));
    vo.setCgUnitPrice(SheetUtils.tryToDecimal(row.getCgUnitPrice()));
    vo.setProportionOfCg(SheetUtils.tryToDecimal(row.getProportionOfCg()));
    vo.setCgTransportCostsTotal(
      SheetUtils.tryToDecimal(row.getCgTransportCostsTotal())
    );
    vo.setHasCgTransportCostsDetail(
      SheetUtils.tryToInteger(row.getHasCgTransportCostsDetail())
    );
    vo.setCgTransportUnitCosts(
      SheetUtils.tryToDecimal(row.getCgTransportUnitCosts())
    );
    vo.setProportionOfCgTransport(
      SheetUtils.tryToDecimal(row.getProportionOfCgTransport())
    );
    vo.setTotalCost(SheetUtils.tryToDecimal(row.getTotalCost()));
    vo.setProportionOfTotalCost(
      SheetUtils.tryToDecimal(row.getProportionOfTotalCost())
    );
    vo.setCgOtherCostsTotal(
      SheetUtils.tryToDecimal(row.getCgOtherCostsTotal())
    );
    vo.setCgOtherUnitCosts(SheetUtils.tryToDecimal(row.getCgOtherUnitCosts()));
    vo.setHasCgOtherCostsDetail(
      SheetUtils.tryToInteger(row.getHasCgOtherCostsDetail())
    );
    vo.setProportionOfCgOtherCosts(
      SheetUtils.tryToDecimal(row.getProportionOfCgOtherCosts())
    );
    vo.setGrossProfit(SheetUtils.tryToDecimal(row.getGrossProfit()));
    vo.setGrossRate(SheetUtils.tryToDecimal(row.getGrossRate()));
    vo.setSid(SheetUtils.tryToInteger(row.getSid()));

    return ir;
  }

  /**
   * 导入预览
   * @param sysFile 已上传到系统的文件
   * @param templateId 要使用的模版编号
   * @param allowOverrides 允许覆盖
   */
  @Override
  public List<ImportRow<ShopProfitReportImportPo>> importPreview(
    SysFile sysFile,
    Long templateId,
    boolean allowOverrides
  ) throws Exception {
    SysImportTemplate importTemplate = null;
    if (templateId != null && templateId > 0) {
      importTemplate = importTemplateService.getById(templateId);
      if (importTemplate == null) {
        throw new RException("指定的模版不可用！");
      }
    }
    Map<String, Object> variables = new HashMap<>();

    // 标记由模版直接导入的字段集
    if (importTemplate != null) {
      variables.put(
        "IMPORT_FIELDS",
        importTemplate
          .getSetting()
          .getMappings()
          .stream()
          .map(SysImportTemplate.Mapping::getField)
          .collect(Collectors.toSet())
      );
    }
    try (InputStream in = fileService.read(sysFile)) {
      List<ImportRow<ShopProfitReportImportPo>> rows = new ArrayList<>();

      // 读取 Excel 到 rows
      EasyExcel
        .read(in)
        .useDefaultListener(false)
        .registerReadListener(
          new TemplateModelBuildEventListener<>(
            ShopProfitReportImportPo.class,
            importTemplate
          ) {
            @Override
            public void invokeRow(
              ShopProfitReportImportPo row,
              AnalysisContext cxt
            ) {
              ShopProfitReportVo vo = new ShopProfitReportVo();
              ImportRow<ShopProfitReportImportPo> ir = excelToImportRow(
                row,
                cxt.readRowHolder().getRowIndex(),
                vo,
                variables,
                allowOverrides
              );
              if (ir.isEmptyRow()) {
                return;
              }
              if (allowOverrides) {
                // FIXME: 未在平台上配置此对象《作为导入唯一识别》的《逻辑分组》配置，无法处理更新模式
              }
              rows.add(ir);
            }
          }
        )
        .sheet()
        .doRead();

      return rows;
    }
  }

  /**
   * 完成导入
   * @param rows 预导入的行信息
   */
  @DataActivity(action = SysDataActivityAction.Import)
  @Transactional(rollbackFor = Exception.class)
  @Override
  public void importDone(
    List<ImportRow<ShopProfitReportImportPo>> rows,
    Long templateId
  ) throws Exception {
    SysImportTemplate importTemplate = null;
    if (templateId != null && templateId > 0) {
      importTemplate = importTemplateService.getById(templateId);
      if (importTemplate == null) {
        throw new RException("指定的模版不可用！");
      }
    }
    String sysImportBatchNo = StrUtil.concat(
      true,
      DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_MS_PATTERN),
      IdUtil.nanoId(4)
    );
    List<Long> importedIdList = new ArrayList<>();
    SysDataActivityAopHelper.clear();
    final SysDataActivityAopHelper.DataActivityAopContext context =
      SysDataActivityAopHelper.getOrCreateContext();
    Map<String, Object> variables = new HashMap<>();

    // 标记由模版直接导入的字段集
    if (importTemplate != null) {
      variables.put(
        "IMPORT_FIELDS",
        importTemplate
          .getSetting()
          .getMappings()
          .stream()
          .map(SysImportTemplate.Mapping::getField)
          .collect(Collectors.toSet())
      );
    }
    for (int i = 0; i < rows.size(); i++) {
      ImportRow<ShopProfitReportImportPo> row = rows.get(i);
      Long updateId = row.getUpdateId();
      ShopProfitReportVo vo = new ShopProfitReportVo();
      row =
        excelToImportRow(row.getRow(), row.getRowNumber(), vo, variables, true);
      if (row.getErrors() != null && row.getErrors().size() > 0) {
        throw new RException(
          String.format(
            "第%d行（Excel第%d行）数据验证错误：%s",
            i + 1,
            row.getRowNumber(),
            row.getJoinErrorMessage()
          )
        );
      }
      if (updateId != null) {
        vo.setId(updateId);
      }
      SheetUtils.setSysImportTemplateName(
        vo,
        null == importTemplate ? "默认模板" : importTemplate.getTitle()
      );
      SheetUtils.setSysImportBatchNo(vo, sysImportBatchNo);
      if (updateId == null) {
        importedIdList.add(create(vo));
      } else {
        self.update(vo);
        importedIdList.add(vo.getId());
      }
    }
    context.getIdList().addAll(importedIdList);
  }

  /**
   * 导出
   * @param templateId 使用模版（可以是 null 或 0 表示系统默认导出模版）
   * @param search 查询条件
   */
  @DataActivity(action = SysDataActivityAction.Export)
  @Override
  public void export(
    Long templateId,
    ShopProfitReportSearchParamPo search,
    HttpServletResponse response
  ) throws Exception {
    if (templateId != null && templateId > 0) {
      SysImportTemplate sysImportTemplate = importTemplateService.getById(
        templateId
      );
      if (sysImportTemplate == null) {
        throw new RException("所选的导出模版不可用");
      }
      CustomExcelExport.CustomExcelExportOptions exportOptions =
        new CustomExcelExport.CustomExcelExportOptions();
      exportOptions.setImportTemplate(sysImportTemplate);
      exportOptions.setSearchParam(search);
      exportOptions.setMainService(this);
      exportOptions.addFieldMappingOption(
        "postedDateLocale",
        new CustomExcelExport.FieldMappingOption()
          .setConverter((o, r) -> DateUtils.toDateString((Date) o))
      );
      exportOptions.addStringFields("storeName", "isPush", "pushResult");

      String fileName = String.format(
        "利润查询报表-店铺(%s).xlsx",
        DateUtils.toString(null, DateUtils.PATTERN_DATE_TIME)
      );
      ResponseUtils.setAttachmentFileName(response, fileName);
      customExcelExport.run(exportOptions, response.getOutputStream());
      return;
    }
    search.setPageSize(EXPORT_QUERY_MAX_SIZE);
    int current = 1;
    List<ShopProfitReportExcelPo> items =
      new ArrayList<ShopProfitReportExcelPo>();
    while (true) {
      search.setCurrent(current);
      search.setSelectFields(Collections.singletonList("@export"));
      Page<ShopProfitReportItemVo> page = this.pageSearch(search);
      if (page.getTotal() > EXPORT_MAX_SIZE) {
        throw new RException("导出记录数超出限制！");
      }
      List<ShopProfitReportItemVo> list = page.getRecords();
      if (list.isEmpty()) {
        break;
      }
      for (ShopProfitReportItemVo item : list) {
        ShopProfitReportExcelPo excel = new ShopProfitReportExcelPo();
        BeanUtils.copyProperties(item, excel);

        items.add(excel);
      }
      if (list.size() < EXPORT_QUERY_MAX_SIZE) {
        break;
      }
      current++;
    }

    String fileName = String.format(
      "利润查询报表-店铺(%s).xlsx",
      DateUtils.toString(null, DateUtils.PATTERN_DATE_TIME)
    );
    ResponseUtils.setAttachmentFileName(response, fileName);
    EasyExcel
      .write(response.getOutputStream())
      .registerWriteHandler(new CustomExcelHandler())
      .sheet()
      .head(ShopProfitReportExcelPo.class)
      .doWrite(items);
  }

  /**
   * 查询币种的搜索自动完成选项
   */
  @Override
  public List<String> getCurrencyCodeAutoComplete() {
    return this.baseMapper.selectCurrencyCodeAutoComplete();
  }

  /**
   * 通过销量查询利润查询报表-店铺主键(重复时返回最新的主键)
   */
  @Override
  public Long getIdByTotalSalesQuantity(Integer totalSalesQuantity) {
    return this.baseMapper.getIdByTotalSalesQuantity(totalSalesQuantity);
  }

  /**
   * 通过销量查询利润查询报表-店铺多主键(重复时返回最新的主键)
   */
  @Override
  public List<Long> getIdsByTotalSalesQuantity(List<Integer> list) {
    return this.baseMapper.getIdsByTotalSalesQuantity(list);
  }

  /**
   * 通过利润查询报表-店铺主键查询销量
   */
  @Override
  public Integer getTotalSalesQuantityById(Long id) {
    return this.baseMapper.getTotalSalesQuantityById(id);
  }

  /**
   * 通过利润查询报表-店铺主键查询销量列表
   */
  @Override
  public List<Integer> getTotalSalesQuantityByIds(List<Long> ids) {
    List<Map<String, Object>> maps =
      this.baseMapper.getTotalSalesQuantityByIds(ids);
    // 将返回重新排列为输入相同顺序
    return ids
      .stream()
      .map(id -> {
        Optional<Map<String, Object>> optionalMap = maps
          .stream()
          .filter(map -> id.equals(map.get("id")))
          .findFirst();
        return optionalMap
          .map(stringObjectMap ->
            (Integer) stringObjectMap.get("totalSalesQuantity")
          )
          .orElse(null);
      })
      .collect(Collectors.toList());
  }

  /**
   * 获取详情
   * @param id 利润查询报表-店铺的主键
   */
  @DataActivity(action = SysDataActivityAction.View)
  @Override
  public ShopProfitReportVo getVoById(Long id) throws Exception {
    ShopProfitReportVo vo = this.baseMapper.selectVoById(id);
    if (vo == null) {
      return null;
    }

    ShopProfitReportOtherFeeSearchParamPo otherFeeStrSearchParamPo =
      new ShopProfitReportOtherFeeSearchParamPo();
    otherFeeStrSearchParamPo.setParentShopProfitReport(id);
    otherFeeStrSearchParamPo.getExtendData().put("queryMode", "sub");
    otherFeeStrSearchParamPo
      .getExtendData()
      .put("queryParent", "ShopProfitReport");
    otherFeeStrSearchParamPo.applySqlSegments();
    vo.setOtherFeeStr(
      shopProfitReportOtherFeeService.search(otherFeeStrSearchParamPo)
    );

    return vo;
  }

  /**
   * 分页查询利润查询报表-店铺
   * @param search 查询条件
   * @return 利润查询报表-店铺分页查询结果
   */
  @Override
  public Page<ShopProfitReportItemVo> pageSearch(
    ShopProfitReportSearchParamPo search
  ) {
    Page<ShopProfitReportItemVo> page = new Page<>();
    if (
      Objects.nonNull(search.getWfStatus()) &&
      StringUtils.hasText(search.getFormName())
    ) {
      List<WorkFlow> workFlowList = workFlowService.queryWfListByStatus(
        search.getWfStatus(),
        search.getFormName()
      );
      if (CollectionUtils.isEmpty(workFlowList)) {
        return page;
      }
      List<Long> ids = workFlowList
        .stream()
        .map(WorkFlow::getRecordId)
        .collect(Collectors.toList());
      if (CollectionUtils.isEmpty(ids)) {
        return page;
      }
      search.setSelectedIds(ids);
    }
    search.initSort("t.id desc", "t.", SORT_FIELD_MAP);
    page = this.baseMapper.pageSearch(search.toPage(), search);
    List<Long> recordIds = page
      .getRecords()
      .stream()
      .map(ShopProfitReportItemVo::getId)
      .collect(Collectors.toList());
    if (CollectionUtils.isEmpty(recordIds)) {
      return page;
    }
    List<WorkFlow> workFlows = workFlowService.queryWfList(
      recordIds,
      Collections.singletonList(search.getFormName())
    );
    if (CollectionUtils.isEmpty(workFlows)) {
      return page;
    }
    Map<Long, Integer> flowMap = workFlows
      .stream()
      .collect(Collectors.toMap(WorkFlow::getRecordId, WorkFlow::getWfStatus));
    page
      .getRecords()
      .stream()
      .forEach(item -> {
        if (!flowMap.containsKey(item.getId())) {
          return;
        }
        item.setWfStatus(flowMap.get(item.getId()));
      });
    return page;
  }

  /**
   * 利润查询报表-店铺快速查询选项(有缓存)
   * @param search 查询条件
   * @return 选项结果
   */
  @Override
  @Cacheable(
    value = CacheConfig.FAST,
    key = "'ShopProfitReportOptions::' + @userInfo.userTypeAndId + '::' + #search.keyword"
  )
  public List<OptionItem<ShopProfitReportItemVo>> searchOptions(
    ShopProfitReportSearchParamPo search
  ) {
    search.initSort("t.id desc", "t.", SORT_FIELD_MAP);
    return this.baseMapper.searchOptions(search);
  }

  /**
   * 列表查询利润查询报表-店铺
   * @param search 查询条件
   * @return 利润查询报表-店铺列表查询结果
   */
  @Override
  public List<ShopProfitReportItemVo> search(
    ShopProfitReportSearchParamPo search
  ) {
    search.initSort("t.id desc", "t.", SORT_FIELD_MAP);
    return this.baseMapper.search(search);
  }

  /**
   * 查询利润查询报表-店铺最后更新时间
   * @param search 查询条件
   * @return 利润查询报表-店铺最后更新时间
   */
  @Override
  public Date searchLastUpdateTime(ShopProfitReportSearchParamPo search) {
    return this.baseMapper.searchLastUpdateTime(search);
  }

  /**
   * 批量推送
   */
  @DataActivity(
    action = SysDataActivityAction.Other,
    message = "%s执行了批量推送操作"
  )
  @Override
  public void batchPushJindie(List<Long> ids) throws Exception {
    if (shopProfitReportBatchPushJindieAction == null) {
      throw new Exception("此操作当前不可用");
    }
    shopProfitReportBatchPushJindieAction.run(ids);
  }

  /**
   * 同步领星数据
   */
  @DataActivity(
    action = SysDataActivityAction.Other,
    message = "%s执行了同步领星数据操作"
  )
  @Override
  public void syncLingXing() throws Exception {
    if (shopProfitReportSyncLingXingAction == null) {
      throw new Exception("此操作当前不可用");
    }
    shopProfitReportSyncLingXingAction.run();
  }

  /**
   * 推送金蝶
   */
  @DataActivity(
    action = SysDataActivityAction.Other,
    message = "%s执行了推送金蝶操作"
  )
  @Override
  public void pushJindie(Long id) throws Exception {
    if (shopProfitReportPushJindieAction == null) {
      throw new Exception("此操作当前不可用");
    }
    shopProfitReportPushJindieAction.run(id);
  }
}
